/*
 * ExternalExperimenter.java
 *
 * Created on den 28 januari 2008, 18:44
 */
package grex.Graphics;

import grex.Data.ArffTableModel;
import grex.ErrorManager;
import grex.EvolutionListener;
import grex.EvolutionProcess;
import grex.Graphics.GREXGUI;
import grex.IPredictiveModel;
import grex.Options;
import grex.genes.GeneException;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.DefaultListModel;
import javax.swing.UIManager;

/**
 *
 * @author RIK
 */
public class ExternalExperimenter extends javax.swing.JFrame implements EvolutionListener {

    DefaultListModel experiments = new DefaultListModel();
    private int nextExperiment = 0;
    private GREXGUI parent;
    private ArrayList<ArffTableModel> models = new ArrayList<ArffTableModel>();
    private String fileName;
    private String options;

    /**
     * Creates new form ExternalExperimenter
     */
    public ExternalExperimenter(GREXGUI parent) {
        setLookAndFeel();
        initComponents();
        this.parent = parent;
        jlstExperiments.setModel(experiments);
        fileName = "ExperimentSummary" + System.currentTimeMillis() + ".grex";
    }

    private void setLookAndFeel() {
        try {
            // Set cross-platform Java L&F (also called "Metal")
            UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            // handle exception
        }
    }

    public void addExperiment(Options ops, ArffTableModel af) {
        experiments.addElement(ops);
        models.add(af);
    }

    private void startExperiment() {

        Options ops = (Options) experiments.getElementAt(nextExperiment);
        parent.startNewGREX(ops, this, models.get(nextExperiment),false);
        int[] indexes = new int[nextExperiment + 1];
        for (int i = 0; i < indexes.length; i++) {
            indexes[i] = i;
        }
        jlstExperiments.setSelectedIndices(indexes);
        nextExperiment++;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jlstExperiments = new javax.swing.JList();
        jbtnStart = new javax.swing.JButton();
        jbtnRemove = new javax.swing.JButton();
        jftfnrOfParalellExperiments = new javax.swing.JFormattedTextField();
        jLabel1 = new javax.swing.JLabel();

        setTitle("G-REX Experimenter");

        jScrollPane1.setViewportView(jlstExperiments);

        jbtnStart.setText("Start");
        jbtnStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnStartActionPerformed(evt);
            }
        });

        jbtnRemove.setText("Remove");
        jbtnRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnRemoveActionPerformed(evt);
            }
        });

        jftfnrOfParalellExperiments.setText("jFormattedTextField1");
        jftfnrOfParalellExperiments.setValue(new Integer(1));

        jLabel1.setText("Number of parallel experiments:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jbtnRemove)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 236, Short.MAX_VALUE)
                        .addComponent(jbtnStart))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jftfnrOfParalellExperiments, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jftfnrOfParalellExperiments, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 227, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jbtnStart)
                    .addComponent(jbtnRemove))
                .addContainerGap(16, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jbtnRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnRemoveActionPerformed
        models.remove(jlstExperiments.getSelectedIndex());
        experiments.remove(jlstExperiments.getSelectedIndex());
    }//GEN-LAST:event_jbtnRemoveActionPerformed

    private void jbtnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnStartActionPerformed
        nextExperiment = 0;
        int exps = (Integer) jftfnrOfParalellExperiments.getValue();
        for (int i = 0; i < exps; i++) {
            startExperiment();
        }
    }//GEN-LAST:event_jbtnStartActionPerformed
    /**
     * @param args the command line arguments
     */
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton jbtnRemove;
    private javax.swing.JButton jbtnStart;
    private javax.swing.JFormattedTextField jftfnrOfParalellExperiments;
    private javax.swing.JList jlstExperiments;
    // End of variables declaration//GEN-END:variables

    public void evolutionStarted(EvolutionProcess source) {
    }

    public void generationTerminated(EvolutionProcess source) {
    }

    public void batchTerminated(EvolutionProcess source) {
    }

    public void evolutionTerminated(EvolutionProcess source) {
        // writeResultsToFile(preds);
        //     writeResultsToFile(options);
    }
    private String headers = "";
    String preds = "";

    Lock lock = new ReentrantLock();
    public void evolutionProcessTerminated(EvolutionProcess source) {
        try {
            lock.lock();
            writeResultsToFile(source.getBatchResult());
            lock.unlock();
         //   writeSensitivityToFile(source.getBatchSensitivity());
          //  preds += source.getBatchResultPredictions();
          //  writeResultsToFile(preds);
        } catch (GeneException ex) {
            ErrorManager.getInstance().reportError(ex);
        }//*/
        options += "\n" + source.getOptions() + "\n";
        if (nextExperiment < experiments.getSize()) {
            startExperiment();
        } else {
            writeResultsToFile(source.getBatchHeaders() + "\n");
     /*       try {
                writeSensitivityToFile(source.getBatchSensitivityHeaders());
            } catch (GeneException ex) {
                Logger.getLogger(ExternalExperimenter.class.getName()).log(Level.SEVERE, null, ex);
            }*/
        }

    }

    private synchronized void writeResultsToFile(String result) {
        try {
            // Create file 
            FileWriter fstream = new FileWriter(fileName, true);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(result);
            //Close the output stream
            out.close();
        } catch (Exception e) {//Catch exception if any
            ErrorManager.getInstance().reportError(e);
        }
    }

    private void writeSensitivityToFile(String sensitivity) {
        try {
            // Create file 
            FileWriter fstream = new FileWriter(fileName + "-Sensitivity", true);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(sensitivity);
            //Close the output stream
            out.close();
        } catch (Exception e) {//Catch exception if any
            ErrorManager.getInstance().reportError(e);
        }
    }
}
